package com.wisdom.core.nacos;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.listener.AbstractEventListener;
import com.alibaba.nacos.api.naming.listener.EventListener;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
import com.alibaba.nacos.client.naming.NacosNamingService;
import com.alibaba.nacos.common.notify.listener.Subscriber;
import com.wisdom.core.exception.RpcException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * @description: <nacos server register>
 * @author: Leo
 * @date:2021-08-21 16:31
 */
@Component
@DependsOn
@Slf4j
public class NacosServerRegister {
    //Nacos未放开 命名空间相关API 因此 默认使用public命名空间 进行服务注册与发现
    //Nacos实例操作
    @Autowired
    private NacosNamingService nacosNamingService;


    private static final boolean IS_SUBSCRIBE = true;
    private static final boolean HEALTHY_SERVICE = true;


    public void registerInstance(String serviceName, String ClusterNames, String ServerIp, int ServerPort, String GroupName, double weight) {
        try {
            if (StringUtils.isBlank(ClusterNames)) {
                nacosNamingService.registerInstance(serviceName, ServerIp, ServerPort, GroupName);
                log.info("注册Nacos非集群服务成功，serviceName:{},ServerIp:{},ServerPort:{},GroupName:{}",
                        serviceName, ServerIp, ServerPort, GroupName);
            } else {
                if (weight != 1.0) {
                    Instance instance = new Instance();
                    instance.setIp(ServerIp);
                    instance.setPort(ServerPort);
                    instance.setWeight(weight);
                    instance.setClusterName(ClusterNames);
                    nacosNamingService.registerInstance(serviceName, GroupName, instance);
                    log.info("注册Nacos非集群服务成功，serviceName:{},ServerIp:{},ServerPort:{},GroupName:{},Weight:{},ClusterNames:{}",
                            serviceName, ServerIp, ServerPort, GroupName, weight, ClusterNames);
                } else {
                    nacosNamingService.registerInstance(serviceName, GroupName, ServerIp, ServerPort, ClusterNames);
                    log.info("注册Nacos非集群服务成功，serviceName:{},ServerIp:{},ServerPort:{},GroupName:{},ClusterNames:{}",
                            serviceName, ServerIp, ServerPort, GroupName, ClusterNames);
                }
            }
        } catch (NacosException e) {
            log.info("注册Nacos服务失败，errorMsg: {}", e.getErrMsg());
            throw new RpcException(e.getErrMsg(), e);
        }
    }


    public void deregisterInstance(String serviceName, String ClusterNames, String ServerIp, int ServerPort, String GroupName, double weight) {
        try {
            if (StringUtils.isBlank(ClusterNames)) {
                nacosNamingService.deregisterInstance(serviceName, ServerIp, ServerPort, GroupName);
                log.info("取消注册Nacos非集群服务成功，serviceName:{},ServerIp:{},ServerPort:{},GroupName:{}",
                        serviceName, ServerIp, ServerPort, GroupName);
            } else {
                if (weight != 1.0) {
                    Instance instance = new Instance();
                    instance.setIp(ServerIp);
                    instance.setPort(ServerPort);
                    instance.setWeight(weight);
                    instance.setClusterName(ClusterNames);
                    nacosNamingService.deregisterInstance(serviceName, GroupName, instance);
                    log.info("取消注册Nacos非集群服务成功，serviceName:{},ServerIp:{},ServerPort:{},GroupName:{},Weight:{},ClusterNames:{}",
                            serviceName, ServerIp, ServerPort, GroupName, weight, ClusterNames);
                } else {
                    nacosNamingService.deregisterInstance(serviceName, GroupName, ServerIp, ServerPort, ClusterNames);
                    log.info("取消注册Nacos非集群服务成功，serviceName:{},ServerIp:{},ServerPort:{},GroupName:{},ClusterNames:{}",
                            serviceName, ServerIp, ServerPort, GroupName, ClusterNames);
                }
            }
        } catch (NacosException e) {
            log.info("取消注册Nacos服务失败，errorMsg: {}", e.getErrMsg());
            throw new RpcException(e.getErrMsg(), e);
        }
    }

    public List<Instance> getAllInstances(String serviceName, List<String> clusters, String GroupName) {
        if (clusters == null || clusters.isEmpty()) {
            clusters = new ArrayList<>();
        }
        try {
            return nacosNamingService.getAllInstances(serviceName, GroupName, clusters, IS_SUBSCRIBE);
        } catch (NacosException e) {
            log.info("获取所有Nacos服务失败，errorMsg: {}", e.getErrMsg());
            throw new RpcException(e.getErrMsg(), e);
        }
    }

    public List<Instance> selectHealthyInstances(String serviceName, String GroupName) {
        try {
            return nacosNamingService.selectInstances(serviceName, GroupName, HEALTHY_SERVICE, IS_SUBSCRIBE);
        } catch (NacosException e) {
            log.info("获取健康的Nacos服务失败，errorMsg: {}", e.getErrMsg());
            throw new RpcException(e.getErrMsg(), e);
        }
    }

    public Instance selectOneHealthyInstance(String serviceName, List<String> clusters, String GroupName) {
        if (clusters == null || clusters.isEmpty()) {
            clusters = new ArrayList<>();
        }
        try {
            return nacosNamingService.selectOneHealthyInstance(serviceName, GroupName, clusters, IS_SUBSCRIBE);
        } catch (NacosException e) {
            log.info("获取单一健康的Nacos服务失败，errorMsg: {}", e.getErrMsg());
            throw new RpcException(e.getErrMsg(), e);
        }
    }

    public <T extends EventListener> void subscribe(String serviceName, List<String> clusters, String groupName, T listener) throws NacosException {
        nacosNamingService.subscribe(serviceName, groupName, clusters, listener);
    }

    public ListView<String> getServicesOfServer(String groupName) {
        ListView<String> serviceNameView = new ListView<>();
        int pageNo = 1;
        int pageSize = 10;
        try {
            ListView<String> listView = nacosNamingService.getServicesOfServer(pageNo, pageSize,groupName);
            serviceNameView.setCount(listView.getCount());
            List<String> serviceNames = new ArrayList<>(listView.getData());
            if (listView.getCount() > pageSize) {
                int size = listView.getCount() % 10;
                for (int i = 2; i <= size; i++) {
                    ListView<String> nextListView = nacosNamingService.getServicesOfServer(i, pageSize);
                    serviceNames.addAll(nextListView.getData());
                }
            }
            serviceNameView.setData(serviceNames);
        } catch (NacosException e) {
            log.info("获取Nacos服务列表信息失败，errorMsg: {}", e.getErrMsg());
            throw new RpcException(e.getErrMsg(), e);
        }
        return serviceNameView;
    }

}
